#include "callbackMem.h"

#define MAX_SIZE 64			/*!< Tamanno maximo de la tabla de registros*/

typedef struct __callbackEntry{
	unsigned int id;						/*!< Identificador*/
	pf_notificacion_echo function;			/*!< Funcion de notificacion*/
} CALLBACK_ENTRY;				/*!< Entrada de tabla de callback*/

struct __callbackMem{
	CALLBACK_ENTRY notifyArray[MAX_SIZE];	/*!< Array de entradas*/
	int last;								/*!< Primera entrada libre*/
};								/*!< Tabla de callback*/

/**
* @brief Busca un id el la EdD, retornando su indice si existe.
*
* @param callMem EdD sobre la que ejecutar la busqueda.
* @param id Identificador a buscar
* @return >=0 indice buscado, <0 si no se hallo el id.
*/
int findCallback(CALLBACK_MEM callMem, unsigned int id);

CALLBACK_MEM createCallbackMem()
{
	CALLBACK_MEM callMem=NULL;
	
	/*Reserva dinamica de memoria para la EdD*/
	callMem=(struct __callbackMem *) calloc(1, sizeof(struct __callbackMem));
	if(callMem==NULL){
		return NULL;
	}
	
	callMem->last=0;
	
	return callMem;
}

void freeCallbackMem(CALLBACK_MEM callMem)
{
	free(callMem);
	
	return;
}

CALLBACK_MEM_ERRCODE registerCallback(CALLBACK_MEM callMem, unsigned int id, pf_notificacion_echo function)
{
	int find;
	
	if(callMem==NULL){
		return CALLBACK_MEM_ERR;
	}
	
	find=findCallback(callMem, id);
	if(find>=0){										/*Id ya registrado -> Actualizacion de la entrada*/
		callMem->notifyArray[find].function=function;
		return CALLBACK_MEM_OK;			
	}
	
	if(callMem->last==(MAX_SIZE-1)){					/*Memoria de la tabla de registros llena*/
		return CALLBACK_MEM_FULL;
	}
	
	/*Insercion de nueva entrada*/
	callMem->notifyArray[callMem->last].id=id;
	callMem->notifyArray[callMem->last].function=function;
	callMem->last++;
	
	return CALLBACK_MEM_OK;
}

pf_notificacion_echo getCallback(CALLBACK_MEM callMem, unsigned int id)
{
	int entryIndex=0;
	
	if(callMem==NULL){
		return NULL;
	}
	
	entryIndex=findCallback(callMem, id);
	if(entryIndex<0){		/*Entrada no encontrada*/
		return NULL;
	}
	
	return callMem->notifyArray[entryIndex].function;
}

int findCallback(CALLBACK_MEM callMem, unsigned int id)
{
	int i;
	short found=0;
	
	if(callMem==NULL){
		return -1;
	}
	
	/*Busqueda secuencial de la entrada*/
	for(i=0; i<callMem->last && !found; i++){
		if(callMem->notifyArray[i].id==id){
			found=1;
		}
	}
	
	if(found){
		return i-1;
	}
	
	return -1;
}

